package com.simple.annotation.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.simple.annotation.Inject;
import com.simple.annotation.Instance;
import com.simple.manager.impl.InstanceManager;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class InjectImpl {

    public static void init() {
        InstanceManager instance = InstanceManager.getInstance();
        Collection<Object> values = instance.values();
        for (Object value : values) {
            Field[] fields = ReflectUtil.getFields(value.getClass());
            List<Field> list = Arrays.stream(fields)
                    .filter(field -> Objects.nonNull(field.getDeclaredAnnotation(Inject.class)))
                    .collect(Collectors.toList());
            for (Field field : list) {
                Inject inject = field.getDeclaredAnnotation(Inject.class);
                String key = inject.value();
                if (StrUtil.isEmpty(key)) {
                    key = field.getType().getName();
                    if (!instance.containsKey(key)) {
                        key = search(key, instance);
                    }
                }
                Object object = instance.get(key);
                ReflectUtil.setFieldValue(value, field, object);
            }
        }
    }

    private static String search(String key, InstanceManager instance) {
        try {
            Class<?> aClass = Class.forName(key);
            List<Object> list = instance.values().stream().filter(aClass::isInstance).collect(Collectors.toList());
            if (list.size() > 1) {
                throw new IllegalStateException("太多的实例");
            } else if (CollUtil.isEmpty(list)) {
                throw new IllegalStateException("找不到指定的实例");
            } else {
                Class<?> clazz = list.get(0).getClass();
                Instance annotation = clazz.getDeclaredAnnotation(Instance.class);
                return StrUtil.isEmpty(annotation.value()) ? clazz.getName() : annotation.value();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}
